package com.mxpio.erp.plan.policy.impl;

import com.mxpio.erp.common.LotStatusUtil;
import com.mxpio.erp.common.enums.*;
import com.mxpio.erp.common.inventory.entity.*;
import com.mxpio.erp.common.jpa.model.Notice;
import com.mxpio.erp.common.jpa.model.NoticeLine;
import com.mxpio.erp.common.jpa.model.NoticeLineKey;
import com.mxpio.erp.common.order.policy.AbstractNoticePolicy;
import com.mxpio.erp.common.order.policy.NoticeContext;
import com.mxpio.erp.common.plan.entity.ODDefectiveRejNoticeLine;
import com.mxpio.erp.common.plan.entity.ODSupplementNotice;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpio.erp.common.vo.OrderExcuteLineVo;
import com.mxpioframework.common.util.BeanReflectionUtils;
import com.mxpioframework.jpa.JpaUtil;
import org.apache.commons.collections4.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 组织需求 不良品退料通知单执行策略
 * @author mxpio
 *
 */
public class DefectiveRejNoticePolicy extends AbstractNoticePolicy {

	private List<OrderExcuteLineVo> orderExcuteVos;

	public DefectiveRejNoticePolicy(List<OrderExcuteLineVo> orderExcuteVos) {
		this.orderExcuteVos = orderExcuteVos;
	}
	
	@Override
	public void execute(NoticeContext context) {
		
	}
	
	@Override
	public NoticeContext config(NoticeContext context) {
		context.setOrderExcuteVos(orderExcuteVos);
		return context;
	}

	//重写apply方法，根据执行提交的明细数据，是否补料。直接生成一个对应的补料通知单。同时更新原通知单明细中的异常信息登记字段
	@Override
	public void apply(NoticeContext context) {
		if(beforeExecute(context)) {
			execute(context);
			Notice notice = context.getEntity();
			List<OrderExcuteLineVo> orderExcuteVos = context.getOrderExcuteVos();
			if (orderExcuteVos.size()>0){
				Set<String> itemCodeSet = orderExcuteVos.stream().map(OrderExcuteLineVo::getItemCode).collect(Collectors.toSet());
				List<Item> itemList = JpaUtil.linq(Item.class).in("itemCode", itemCodeSet).list();
				Map<Object, Item> itemMap = JpaUtil.index(itemList, "itemCode");

				WarehouseOrder wo = null;
				int lineNo = 0;
				//补料通知单
				Map<String, ODSupplementNotice> noticeAddMap = new HashMap<>();
				Map<String,List<OrderExcuteLineVo>> voAddMap = new HashMap<>();
				for(OrderExcuteLineVo vo : orderExcuteVos){
					//回写不良品退料通知单明细中的字段数据
					NoticeLineKey noticeLineKey = new NoticeLineKey();
					noticeLineKey.setNoticeNo(vo.getNoticeNo());
					noticeLineKey.setLineNo(vo.getNoticeLineNo());
					ODDefectiveRejNoticeLine dBODDefectiveRejNoticeLine = JpaUtil.getOne(ODDefectiveRejNoticeLine.class, noticeLineKey);
					if (dBODDefectiveRejNoticeLine!=null){
						dBODDefectiveRejNoticeLine.setReporter(vo.getReporter());
						dBODDefectiveRejNoticeLine.setReportProc(vo.getReportProc());
						dBODDefectiveRejNoticeLine.setExceptionType(vo.getExceptionType());
						dBODDefectiveRejNoticeLine.setDefectiveReason(vo.getDefectiveReason());
						dBODDefectiveRejNoticeLine.setDefectiveDesc(vo.getDefectiveDesc());
						dBODDefectiveRejNoticeLine.setResponseUnit(vo.getResponseUnit());
						JpaUtil.update(dBODDefectiveRejNoticeLine);
					}
					if ("1".equals(vo.getSupplementFlag())
							||"Y".equals(vo.getSupplementFlag())
							||"是".equals(vo.getSupplementFlag())){//是否需要生成补料通知单
						ODSupplementNotice noticeAdd = noticeAddMap.get(vo.getBomWhCode());
						if(noticeAdd == null) {
							noticeAdd = (ODSupplementNotice) BeanReflectionUtils.newInstance(ODSupplementNotice.class);
							noticeAdd.setBizOrderNo(vo.getBizOrderNo());

							noticeAdd.setNoticeDate(new Date());
							noticeAdd.setWhCode(vo.getBomWhCode());//取原订单bom子表中的仓库信息
							noticeAdd.setAccessType(OrderEnums.AccessType.OUT.getCode());
							noticeAdd.setPickingType(NoticeStatusEnums.NoticeType.MO_M_REOUT.getCode());//生产补料
							noticeAdd.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CREATE.getStatusCode());
							noticeAddMap.put(vo.getBomWhCode() , noticeAdd);
							voAddMap.put(vo.getBomWhCode() , new ArrayList<OrderExcuteLineVo>());
						}
						voAddMap.get(vo.getBomWhCode()).add(vo);
					}
					//生产仓单
					lineNo++;
					if(wo == null){
						wo = new WarehouseOrder();
						wo.setAccessType(notice.getAccessType());
						wo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
						wo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
						wo.setOrderStatus(OrderStatusEnums.OrderStatus.PLAN.getStatusCode());
						wo.setOrderDate(new Date());
						wo.setOriginBizNo(vo.getBizOrderNo());
						wo.setWhCode(vo.getWhCode());//前端已经传递报废属性的仓库
						//wo.setWhCode(warehouseList.get(0).getWhCode());//生成的仓单对应的仓库应该是仓储属性是报废的仓库
						wo.setWoType(notice.getPickingType());
						wo.setOriginNoticeNo(notice.getNoticeNo());//关联noticeno字段
						JpaUtil.save(wo);
					}
					WarehouseOrderLine line = new WarehouseOrderLine();
					line.setWhCode(wo.getWhCode());
					line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
					Item item = JpaUtil.linq(Item.class).idEqual(vo.getItemCode()).findOne();
					line.setItemCode(vo.getItemCode());
					line.setItemGroupCode(item.getItemGroupCode());
					line.setItemName(item.getItemName());
					line.setItemSpec(item.getItemSpec());
					line.setUnitCode(item.getUnitCode());
					line.setDrawingNo(item.getDrawingNo());
					line.setQuantity(vo.getQuantity());
					line.setBizNo(wo.getBizNo());
					line.setLineNo(lineNo+"");
					line.setOriginBizNo(vo.getBizOrderNo());
					line.setOriginBizLineNo(vo.getBizOrderlineNo());
					line.setSort(vo.getSort());
					line.setLotNo(vo.getLotNo());//
					//拆批 新生成批次索引
					Long count = JpaUtil.linq(Lot.class).equal("lotNo", vo.getLotNo()).count();
					line.setSubLotIndex(count.toString());//子批索引
					//
					Lot lot = new Lot();
					lot.setLotNo(vo.getLotNo());
					String binaryString = LotStatusUtil.toBinaryString("0");//默认正常
					lot.setLotStatus(LotStatusUtil.switchBinaryByIndex(binaryString, InspectionEnums.LotStatusBitIndex.IB14.getIndex()));

					lot.setSubLotIndex(line.getSubLotIndex());
					JpaUtil.save(lot);

					line.setOriginNoticeNo(notice.getNoticeNo());
					line.setOriginNoticeLineNo(vo.getNoticeLineNo());
					JpaUtil.save(line);
				}

				// 生成补料通知单明细
				if (!noticeAddMap.isEmpty()){
					for(Map.Entry<String,ODSupplementNotice> entry : noticeAddMap.entrySet()) {
						ODSupplementNotice addnotice = entry.getValue();
						JpaUtil.save(addnotice);
						int innerlineNo = 0;
						for(OrderExcuteLineVo vo : voAddMap.get(entry.getKey())) {
							innerlineNo++;
							NoticeLine line = addnotice.createLine(vo);
							line.setLineNo(innerlineNo+"");
							line.setLotNo("");//去掉批次信息
							line.setSubLotIndex("");//去掉批次信息
							Item item = JpaUtil.linq(Item.class).idEqual(vo.getItemCode()).findOne();
							line.setItemName(item.getItemName());
							line.setItemSpec(item.getItemSpec());
							line.setUnitCode(item.getUnitCode());
							line.setDrawingNo(item.getDrawingNo());
							JpaUtil.save(line);
						}
					}
				}
			}
			afterExecute(context);
			notice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CONFIRM.getStatusCode());
			JpaUtil.update(notice);
		} else {
			if(CollectionUtils.isEmpty(context.getErrors())) {
				context.addError("前置校验不通过");
			}
		}

	}

	@Override
	public boolean beforeExecute(NoticeContext context) {
		return true;
	}

	@Override
	public void afterExecute(NoticeContext context) {
		
	}

}
